#include <GL/freeglut.h>
#include <cstdlib>
#include <cmath>
using namespace std;

GLsizei winWidth = 600;
GLsizei winHeight = 600;

// 设置世界坐标系显示范围
GLfloat xwcMin = 0, xwcMax = 225;
GLfloat ywcMin = 0, ywcMax = 225;

// 定义二维点数据结构
struct wcPt2D
{
    GLfloat x, y;
};
// using mat3x3 = GLfloat[3][3];
typedef GLfloat Matrix3x3[3][3];
Matrix3x3 matComposite; // 定义复合矩阵
const GLdouble pi = 3.14159;
void init()
{
    glClearColor(1, 1, 1, 0);
}
// 构建3*3单位矩阵
void matrix3x3SetIdentity(Matrix3x3 matIdent3x3)
{
    GLint row, col;
    for (row = 0; row < 3; row++)
        for (col = 0; col < 3; col++)
            matIdent3x3[row][col] = (row == col);
}
// 变换矩阵m1前将m1与矩阵m2相乘,并将结果存入m2
void matrix3x3PreMultiply(Matrix3x3 m1, Matrix3x3 m2)
{
    GLint row, col;
    Matrix3x3 matTemp;
    for (row = 0; row < 3; row++)
        for (col = 0; col < 3; col++)
            matTemp[row][col] = m1[row][0] * m2[0][col] + m1[row][1] * m2[1][col] + m1[row][2] * m2[2][col];
    for (row = 0; row < 3; row++)
        for (col = 0; col < 3; col++)
            m2[row][col] = matTemp[row][col];
}
// 平移变换
void translate2D(GLfloat tx, GLfloat ty)
{
    Matrix3x3 matTrans;
    matrix3x3SetIdentity(matTrans);
    matTrans[0][2] = tx;
    matTrans[1][2] = ty;
    matrix3x3PreMultiply(matTrans, matComposite);
}

// 旋转变换
void rotate2D(wcPt2D pivotPt, GLfloat theta)
{
    Matrix3x3 matRot;
    matrix3x3SetIdentity(matRot);
    matRot[0][0] = cos(theta);
    matRot[0][1] = -sin(theta);
    matRot[0][2] = pivotPt.x * (1 - cos(theta)) + pivotPt.y * sin(theta);
    matRot[1][0] = sin(theta);
    matRot[1][1] = cos(theta);
    matRot[1][2] = pivotPt.y * (1 - cos(theta) - pivotPt.x * sin(theta));

    matrix3x3PreMultiply(matRot, matComposite);
}

// 比例变换，基准点为fixedPt
void scale2D(GLfloat sx, GLfloat sy, wcPt2D fixedPt)
{
    Matrix3x3 matScale;
    matrix3x3SetIdentity(matScale);
    // 自己推导一下，任意基准点放缩的变换矩阵
    matScale[0][0] = sx;
    matScale[0][2] = (1 - sx) * fixedPt.x;
    matScale[1][1] = sy;
    matScale[1][2] = (1 - sy) * fixedPt.y;

    matrix3x3PreMultiply(matScale, matComposite);
}

// 利用复合矩阵计算变换后的坐标
void transformVerts2D(GLint nVerts, wcPt2D *verts)
{
    GLint k;
    GLfloat temp;
    for (k = 0; k < nVerts; k++)
    {
        temp = matComposite[0][0] * verts[k].x + matComposite[0][1] * verts[k].y + matComposite[0][2];
        verts[k].y = matComposite[1][0] * verts[k].x + matComposite[1][1] * verts[k].y + matComposite[1][2];
        verts[k].x = temp;
    }
}

// 三角形绘制
void triangle(wcPt2D *verts)
{
    GLint k;
    glBegin(GL_TRIANGLES);
    for (k = 0; k < 3; k++)
        glVertex2f(verts[k].x, verts[k].y);
    glEnd();
}

void display()
{
    GLint nVerts = 3;
    wcPt2D verts[3] = {{50, 25}, {150, 25}, {100, 100}};
    // 计算三角形中心点
    wcPt2D centerPt;
    GLint k, xSum = 0, ySum = 0;
    for (k = 0; k < nVerts; k++)
    {
        xSum += verts[k].x;
        ySum += verts[k].y;
    }
    centerPt.x = GLfloat(xSum) / GLfloat(nVerts);
    centerPt.y = GLfloat(ySum) / GLfloat(nVerts);
    // 设置几何变换参数
    wcPt2D pivPt, fixedPt;
    pivPt = centerPt;
    fixedPt = centerPt;
    GLfloat tx = 0, ty = 100;
    GLfloat sx = 0.5, sy = 0.5;
    GLdouble theta = pi / 2.0;
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0, 0, 1); // 蓝色三角形
    triangle(verts);

    matrix3x3SetIdentity(matComposite);

    scale2D(sx, sy, fixedPt); // 1.缩放
    rotate2D(pivPt, theta);   // 2.旋转
    translate2D(tx, ty);      // 3.平移
    // 应用复合阵到三角形
    transformVerts2D(nVerts, verts);

    glColor3f(1, 0, 0); // 红色三角形
    triangle(verts);

    glFlush();
}

void reshape(GLint width, GLint height)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(xwcMin, xwcMax, ywcMin, ywcMax);
    glClear(GL_COLOR_BUFFER_BIT);
}

void main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(winWidth, winHeight);
    glutCreateWindow("二维几何变换");

    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    glutMainLoop();
}
